package com.accounting.client.frontend.product;

import java.util.List;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.StockLocation;
import com.accounting.client.remote.obj.Product;
import com.accounting.client.remote.obj.Stock;
import com.accounting.client.remote.transfer.SearchStockRequest;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.SessionManager;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import corelib.client.CollectionUtil;
import corelib.client.NumberFormats;
import corelib.client.Util;
import corelib.client.resource.CommonResources;
import corelib.client.schedule.DeferredTask;
import corelib.client.search.PagingRequest;
import corelib.client.search.PagingResult;
import corelib.client.ui.SimpleMask;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.SimpleDataModel;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.dialog.SimpleLargeDialogHandler;
import corelib.client.ui.widget.form.SelectField;
import corelib.client.ui.widget.form.SimpleLabel;
import corelib.client.ui.widget.form.fomatters.ValueFormatter;
import corelib.client.ui.widget.grid.SimpleDataGrid;
import corelib.client.ui.widget.grid.SimpleDataGridHandler;
import corelib.client.ui.widget.grid.cell.CellRenderer;
import corelib.client.ui.widget.grid.column.ColumnConfig;
import corelib.client.ui.widget.grid.column.ColumnConfigs;
import corelib.client.ui.widget.layout.RelativeRow;
import corelib.client.ui.widget.panel.SimpleLayoutPanel;
import corelib.client.ui.widget.toolbar.SimpleRibbon;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton.ButtonSize;

public class ProductStockManager extends SimpleLargeDialogHandler {
	
	private final static int MaxRecordsPerPage = 20;
	
	private int currentOffset = 0;
	private int currentRecordsPerPage = 0;
	
	private SimpleDataGrid<Stock> stockTable;
	private SimpleStockTableHandler stockTableHandler;
	
	private SelectField<Product> productField;
	private SelectField<StockLocation> locationField;
	
	private SimpleRibbon ribbon;
	private RelativeRow  toolBar;
	
	private SimpleRibbonButton syncBtn;
	private SimpleRibbonButton previousBtn;
	private SimpleRibbonButton nextBtn;

	@Override
	public Widget getContentPanel() {
		ribbon = createRibbon();
		initToolBar();
		
		stockTable = new SimpleDataGrid<Stock>(
			MaxRecordsPerPage, 
			stockTableHandler = new SimpleStockTableHandler()
		);
		
		SimpleLayoutPanel layout = new SimpleLayoutPanel();
		layout.add(ribbon);
		layout.add(stockTable);
		layout.setWidgetTopHeight(ribbon,     0,   Unit.PX, 103,Unit.PX);
		layout.setWidgetTopBottom(stockTable, 103, Unit.PX, 0, Unit.PX);
		return layout;
	}
	
	protected SimpleRibbon createRibbon() {
		toolBar = new RelativeRow();
		SimpleRibbon simpleRibbon = new SimpleRibbon();
		simpleRibbon.addPushButton(syncBtn = new SimpleRibbonButton("同步库存", BoxResources.INSTANCE.sync32(),
				ButtonSize.Medium, new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					Stock stock = stockTable.getSelectedObject();
					if (stock != null){
						sync(stock);	
					}
				}
	    }));
		simpleRibbon.addPushButton(new SimpleRibbonButton("刷新", CommonResources.INSTANCE.refresh32(),
				ButtonSize.Medium, new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					search(0);
				}
	    }));
		simpleRibbon.addSeparator(ButtonSize.Medium);
		simpleRibbon.addPushButton(previousBtn = new SimpleRibbonButton("前页",
				CommonResources.INSTANCE.prev32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						search(Math.max(currentOffset - MaxRecordsPerPage, 0));
					}
				}
		));
		simpleRibbon.addPushButton(nextBtn = new SimpleRibbonButton("后页",
				CommonResources.INSTANCE.next32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						search(Math.max(currentOffset + MaxRecordsPerPage, 0));
					}
				}
		));
		simpleRibbon.addPushButton(new SimpleRibbonButton("关闭",
				CommonResources.INSTANCE.close32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						closeDialog();
					}
				}
		), Style.Float.RIGHT);
		
		syncBtn.setEnabled(false);
		previousBtn.setEnabled(false);
		nextBtn.setEnabled(false);
		simpleRibbon.addLineBreak();
		simpleRibbon.addWidget(toolBar.getPanel());
		return simpleRibbon;
	}
	
	protected void initToolBar() {
		final WidgetListener listener = new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				search(currentOffset);
			}
		};
		
		locationField = new SelectField<StockLocation>(StockLocation.All,listener);
		locationField.setNullable(true);
		locationField.setOptionFormatter("请选择库存位置", new ValueFormatter<StockLocation>(){
			@Override
			public String format(StockLocation value) {
				return value.getCname();
			}
		});
		
		productField = new SelectField<Product>(listener);
		productField.setNullable(true);
		productField.setOptionFormatter("请选择产品", new ValueFormatter<Product>(){
			@Override
			public String format(Product value) {
				return value.getCName();
			}			
		});
		toolBar.add(productField,200)
		       .addSpace(25)
		       .add(locationField,200);
	}
	
	@Override
	public void onShowing() {
		super.onShowing();
		new DeferredTask().run(new ScheduledCommand(){
			@Override
			public void execute() {
				search(0);
				loadProducts();
			}
		}, 400);
	}

	private void loadProducts() {
		PagingRequest request = new PagingRequest();
		request.setOffset(0);
		request.setLimit(1000);
		request.setKeyword(Util.EMPTY_STRING);
		
		Services.ProductService.ListProductsByKeyword(SessionManager.getPassport(), request, new AsyncCallback<PagingResult<Product>>(){
			@Override
			public void onFailure(Throwable caught) {
				ErrorHandler.handleServiceError(caught);
			}
			
			@Override
			public void onSuccess(PagingResult<Product> result) {
				productField.setOptions(result.getData());
			}
		});
	}
	
	private void search(int offset) {
		SimpleModal.show("加载中。。。");
		SearchStockRequest request = new SearchStockRequest();
		request.setOffset(offset);
		request.setLimit(MaxRecordsPerPage);
		if (locationField.getSelectedOption() == null){
			request.setLocation(null);	
		}
		else {
			request.setLocation(locationField.getSelectedOption().getLocation());
		}
		
		if (productField.getSelectedOption() == null){
			request.setProductId(null);
		}
		else {
			request.setProductId(productField.getSelectedOption().getProductId());
		}
		
		Services.ProductService.SearchStocks(SessionManager.getPassport(), request,
			new AsyncCallback<PagingResult<Stock>>() {
				@Override
				public void onFailure(Throwable caught) {
					SimpleModal.hide();
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(PagingResult<Stock> result) {
					SimpleModal.hide();
					currentOffset = result.getOffset();
					currentRecordsPerPage = result.getData().size();
					
					stockTableHandler.setObjects(result.getData());
					syncBtn.setEnabled(false);
					previousBtn.setEnabled(currentOffset > 0);
					nextBtn.setEnabled(currentOffset + currentRecordsPerPage < result.getTotal());
				}
			}
		);
	}
	
	private void sync(Stock stock) {
		SimpleMask.mask(getDialog(), "同步更新。。。");
		String passport = SessionManager.getPassport();
		Services.ProductService.SyncStock(passport, stock.getProductId(), stock.getLocation(),
			new AsyncCallback<Boolean>(){
				@Override
				public void onFailure(Throwable caught) {
					SimpleMask.unmask(getDialog());
					ErrorHandler.handleServiceError(caught);
				}

				@Override
				public void onSuccess(Boolean result) {
					SimpleMask.unmask(getDialog());
					if (result == Boolean.TRUE){
						search(currentOffset);
					}
				}
			}
		);
	}
	
	private class StockCellRenderer extends CellRenderer<Stock> {
		@Override
		public void render(SimpleDataModel<Stock> model,
						   ColumnConfig columnConfig, 
						   int rowIndex, 
						   int colIndex,
						   SafeHtmlBuilder sb) {
			Stock info = model.getObject();
			if (info.getStock() <= 0){
				sb.append(SimpleLabel.createDanger(info.getStock()+"").asSafeHtml());	
			}
			else {
				sb.append(SimpleLabel.createSuccess(info.getStock()+"").asSafeHtml());	
			}
		}
	}
	
	private class SimpleStockTableHandler extends SimpleDataGridHandler<Stock> {
		
		private final static String ProductName  = "ProductName";
		private final static String Count 		 = "Count";
		private final static String Location	 = "Location";
		private final static String Price 		 = "Price";
		private final static String Postage 	 = "Postage";
		
		private List<Stock> data;
		
		@Override
		public List<ColumnConfig> createColumns() {
			List<ColumnConfig> configs = CollectionUtil.newArrayList();
			configs.add(ColumnConfigs.create(ProductName, "产品名称", 100));
			configs.add(ColumnConfigs.create(Count,       "库存数量", 50,  new StockCellRenderer()));	
			configs.add(ColumnConfigs.create(Location, 	  "库存位置", 30));
			configs.add(ColumnConfigs.create(Price,       "产品均价(单件)", 100, NumberFormats.AUD));
			configs.add(ColumnConfigs.create(Postage,     "入库邮费(单件)", 100, NumberFormats.AUD));
			return configs;
		}

		@Override
		public void format(int index, SimpleDataModel<Stock> model) {
			Stock stock = model.getObject();
			model.set(ProductName, stock.getProductName());
			model.set(Location,    StockLocation.getLocationByType(stock.getLocation()).getCname());
			model.set(Count, 	   stock.getStock());
			model.set(Price, 	   stock.getPrice());
			model.set(Postage, 	   stock.getPostage());
		}
		
		public void setObjects(List<Stock> objects){
			data = objects;
			getGrid().setObjects(objects);
		}
		
		@Override
		public List<Stock> getObjects() {
			return SimpleStockTableHandler.this.data;
		}

		@Override
		public void onObjectClicked(Stock obj) {
			if (obj != null){
				syncBtn.setEnabled(true);
			}
		}

		@Override
		public void onObjectDoubleClicked(Stock obj) {
			onObjectClicked(obj);
		}
	}

}
